package com.sifang.sfuserservice.config;


import com.alibaba.fastjson.JSON;
import com.sifang.sfuserservice.annotation.LogAnnotation;
import lombok.RequiredArgsConstructor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Calendar;

@Component
@Aspect
@RequiredArgsConstructor
public class LogAspect {

    // 引入日志配置
    private static final Log logger = LogFactory.getLog(LogAspect.class);

    @Pointcut("@annotation(com.sifang.sfuserservice.annotation.LogAnnotation)")
    public void logPointcut() {
    }

    // around(和上面方法名一样)
    @Around("logPointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        Method method = signature.getMethod();
        LogAnnotation annotation = method.getAnnotation(LogAnnotation.class);
        String module = annotation.module();
        String operator = annotation.operator();

        //log.info("========== Method  start ==========");
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        HttpServletRequest request = attributes.getRequest();
        long start = System.currentTimeMillis();
        Calendar requestTime = Calendar.getInstance();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String reqTime = simpleDateFormat.format(requestTime.getTime());
        //System.out.println("请求时间: " + reqTime);
        //Thread thread = Thread.currentThread();
        String requestParam = JSON.toJSONString(joinPoint.getArgs()[joinPoint.getArgs().length - 1]);
        try {
            Object result = joinPoint.proceed();
            long end = System.currentTimeMillis();
            assemLogMap(joinPoint, request, start, reqTime, result, end, module, operator, requestParam);
            return result;
        } catch (Throwable e) {
            long end = System.currentTimeMillis();
            StringWriter sw = new StringWriter();
            e.printStackTrace(new PrintWriter(sw,true));
            String msg = sw.toString();
            assemLogMap(joinPoint, request, start, reqTime, msg, end, module, operator, requestParam);
            throw e;
        }
    }

    private void assemLogMap(ProceedingJoinPoint joinPoint, HttpServletRequest request, long start, String reqTime, Object result, long end, String module, String operator, String requestParam) {
//        HashMap<String, Object> logMap = new HashMap<>();
//        logMap.put("time", reqTime);
//        logMap.put("request_path", request.getRequestURI());
//        logMap.put("ip", request.getRemoteAddr());
//        logMap.put("request_method", request.getMethod());
//        logMap.put("class_method: ", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
//        logMap.put("request_param: ", joinPoint.getArgs()[joinPoint.getArgs().length - 1]);
//        logMap.put("cost_time: ",(end - start) + "ms");
//        logMap.put("response_result: ",JSON.toJSON(result));
//        log.info(JSON.toJSONString(logMap));


        StringBuilder sb = new StringBuilder();
        sb.append(System.getProperty("line.separator"));
        sb.append("============================== Method  start ==============================").append(System.getProperty("line.separator"));
        sb.append("模块名: ").append(module).append(System.getProperty("line.separator"));
        sb.append("请求方法名称: ").append(operator).append(System.getProperty("line.separator"));
        sb.append("请求方式: ").append(request.getMethod()).append(System.getProperty("line.separator"));
        sb.append("请求时间: ").append(reqTime).append(System.getProperty("line.separator"));
        sb.append("请求地址: ").append(request.getRequestURI()).append(System.getProperty("line.separator"));
        sb.append("用户IP: ").append(request.getRemoteAddr()).append(System.getProperty("line.separator"));
        sb.append("CLASS_METHOD: ").append(joinPoint.getSignature().getDeclaringTypeName()).append(".").append(joinPoint.getSignature().getName()).append(System.getProperty("line.separator"));
        sb.append("请求参数: ").append(requestParam).append(System.getProperty("line.separator"));
        sb.append("执行时间: ").append(end - start).append("ms").append(System.getProperty("line.separator"));
        sb.append("返回结果: ").append(JSON.toJSONString(result)).append(System.getProperty("line.separator"));
        sb.append("============================== Method  End ==============================").append(System.getProperty("line.separator"));
        logger.info(sb.toString());


//        log.info("请求时间: " + reqTime);
//        log.info("请求地址: " + request.getRequestURI());
//        log.info("用户IP: " + request.getRemoteAddr());
//        log.info("请求方法: " + request.getMethod());
//        log.info("CLASS_METHOD: " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
//        log.info("请求参数: " + JSON.toJSONString(joinPoint.getArgs()[joinPoint.getArgs().length - 1]));
//        log.info("执行时间: " + (end - start) + "ms");
//        log.info("返回结果: " + JSON.toJSONString(result));
//        log.info("========== Method  End ==========\n");
    }
}
